<html>
<script>
/*
0 1
1 2
3 3
*/
var total = [0, 1, 2, 3].reduce(function(a, b){ 
	console.log("a: " + a + " b: " + b);
	return a + b; 
	});
// document.writeln("total is : " + total ); // 6

var singleNumber = function(nums) {
  return nums.reduce(function(pre, item) {
    return pre ^ item;
  });
};

// document.writeln("single is: " + singleNumber([1,2,1,2,3]));

/*
我们也可以按位运算，计算1 bit的数量，如果每个数字都出现三次，那么每位上的1 bit数量肯定是3的倍数，相反如果不是3的倍数，那么就是那个特殊的数在捣蛋。
我们似乎需要这么一种“加法”运算，使得每位上的 1 bit 数量能够得到累计，并且累计到了3就自动清零。但是理想是美好的，现实是残酷的，并没有这样一种神奇的运算（三进制？）。
但是我们可以用一个数“辅助”，因为每一位的1 bit数量统计都是类似的，所以假设正在统计某一位的1 bit数量。我们用a来表示 1 bit 的数量，当 1 bit 的数量为0时，a=0；当数量为1时，a=1；当数量为2时，a=2？非也，位运算只能表示0和1，所以这时我们引进第二个变量b，我们用b=1来代表已经有了2个 1 bit，所以当有两个 1 bit 时，a=0,b=1。数量统计结果逢3化0，所以只有0、1、2三种结果：
bits数量    a     b
   0        0     0
   1        1     0
   2        0     1
*/

var singleNumber2 = function(nums){
  var a = 0, b = 0;
  nums.forEach(function(item){
    b = a & (b ^ item);
    a = b | (a ^ item);
    console.log("a: " + a + " b: " + b);
  });

  return a;
};

document.writeln("double is: " + singleNumber2([1,2,1,2,1,2,3]));

/*
还是一个数组，每个元素出现两次，只有两个特殊的元素出现一次，把这两个特殊的元素找出来。
两个特殊的元素？这时候直接异或也并没有什么卵用了啊...以数组[1, 1, 2, 2, 3, 3, 4, 5]举例，如何把4和5找出来？一个数组中有两个特殊的数字，不能用异或运算得到结果，如果只有一个了呢？没错，我们可以把4和5根据某一规则分到两个数组中，然后在各自数组中进行异或从而得到结果。
那么如何分配？我们把4和5用二进制表示出来看看：
1 0 0
1 0 1
因为两个数字不相同，所以它们的二进制码肯定有一位是不同的。我们只需找出这一位，然后根据这一位上是0是1，将数组所有元素分到两个新的数组中，这时4和5肯定已经被分到了不同的数组中，而其余两个相同的数字肯定在一个数组中，这时就能分别对两个数组进行异或运算了。
关于这一位，可以找右数第一个不同位，把两数异或找出右边第一个1即可，而两数的异或其实就是原数组所有元素的异或。*/

var singleNumber4 = function(nums){
  var tmp = nums.reduce(function(pre, item){
    return pre ^ item;
  });

  var one = tmp & (-tmp); // 取右数第一位1
  var a = [], b = [];

  nums.forEach(function(item){
    item & one ? a.push(item) : b.push(item);
  });


  return [
    a.reduce(function(pre, item){
      return pre ^ item;
    }), 

    b.reduce(function(pre, item){
      return pre ^ item;
    })
  ];
};

document.writeln("result: " + singleNumber4([1,1,2,2,3,3,4,5]));
</script>
</html>